package cn.xxstudy.blog.config

import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.*
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import kotlin.math.log

/**
 * 作者：wuxinxi on 2020/11/24
 * 包名：cn.xxstudy.blog.config
 * TODO:全局Controller请求日志
 */
@Aspect
@Component
class GlobalLogAspectHandler {

    private val logger = LoggerFactory.getLogger(this::class.java)

    /**
     * 指定一个切面
     */
    @Pointcut("execution(* cn.xxstudy.blog.controller..*.*(..))")
    fun logCut() {
    }

    @Before("logCut()")
    fun doBefore(joinPoint: JoinPoint) {
        val signature = joinPoint.signature
        val declaringTypeName = signature.declaringTypeName
        val method = signature.name
        val args = joinPoint.args

        val attributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes
        val request = attributes.request
        val ip = request.remoteAddr
        val url = request.requestURL.toString()

        logger.info("request ip : $ip")
        logger.info("request url : $url")
        logger.info("request controller : $declaringTypeName  >>> $method")
        logger.info("request params : ${args.toList()}")
    }

    @After("logCut()")
    fun doAfter(joinPoint: JoinPoint) {
        val signature = joinPoint.signature
        val method = signature.name
        logger.info("$method request finished")
    }

    @AfterReturning(pointcut = "logCut()", returning = "result")
    fun doAfterReturning(joinPoint: JoinPoint, result: Any) {
        val signature = joinPoint.signature
        val method = signature.name
        logger.info("$method response finished")
    }

    @AfterThrowing(pointcut = "logCut()", throwing = "ex")
    fun doAfterThrowing(joinPoint: JoinPoint, ex: Throwable) {
        val signature = joinPoint.signature
        val method = signature.name
        logger.error("$method exception ${ex.message}")
    }
}